<template>
	<view class="ifun-tree-picker">
		<picker mode="multiSelector" :value="selectIndex" ref="picker" :range-key="options.label" :range="viewData"
			:disabled="disabled" @columnchange="handleChange" @change="handleConfirm" @cancel="handleClose">
			<slot>
				<text v-if="selectText">{{ selectText }}</text>
				<text v-else class="picker-label-placeholder">{{ placeholder }}</text>
			</slot>
		</picker>
	</view>
</template>

<script>
	// 节点信息映射
	const DefaultOptions = {
		label: "label",
		value: "value",
		key: "label",
		children: "children",
	};
	export default {
		name: "ifun-tree-picker",
		props: {
			disabled: Boolean,
			data: {
				type: Array,
				default: () => [],
			},
			treeOptions: {
				type: Object,
				defautl: () => ({}),
			},
			value: {
				type: [Object, Array],
				default: () => ({}),
			},
			clearable: Boolean,
			checkStrictly: Boolean,
			placeholder: {
				type: String,
				default: "请选择",
			},
			valueFormat: Function,
			lazy: {
				type: Boolean,
				default: false,
			},
			load: Function,
			// 搜索
			// filterable: Boolean,
			// filterMethod: Function
		},
		data() {
			return {
				selectValue: [],
				// picker 的自身属性
				selectIndex: [],
				// 当前的节点数据
				viewData: [],
			};
		},
		watch: {
			data: {
				immediate: true,
				deep: true,
				handler(arr) {
					this.init(arr);
				},
			},
			value: {
				// immediate: true,
				deep: true,
				handler() {
					// 处理默认值
					this.handleFormatDefault(this.value);
					this.viewData.length = 1;
					// 初始化数据
					this.initViewData();
				},
			},
		},
		computed: {
			options() {
				return {
					...DefaultOptions,
					...this.treeOptions,
				};
			},
			selectText() {
				let len = this.selectValue.length;
				if (len < 1) {
					return "";
				}
				if (this.valueFormat && typeof this.valueFormat == "function") {
					return this.valueFormat(this.selectValue);
				}
				return this.selectValue[len - 1][this.options.label];
			},
		},
		methods: {
			init(data) {
				// 默认第一条数据
				this.viewData = [JSON.parse(JSON.stringify(data))];
				// this.viewData = [arr];
				// 是否严格遵循父子节点不关联
				if (this.checkStrictly) {
					this.handleFormatData(this.viewData[0]);
				}
				if (this.clearable) {
					const {
						value,
						label
					} = this.options;
					this.viewData[0].unshift({
						[value]: "",
						[label]: "",
					});
				}

				// 处理默认值
				this.handleFormatDefault(this.value);
				// 初始化后续的数据
				this.initViewData();
			},
			handleSearch({
				detail
			}) {
				const {
					value
				} = detail;
				if (this.filterMethod && typeof this.filterMethod === "function") {
					// 自定义搜索
					this.filterMethod();
					return;
				}
				if (value === "") {
					this.init(this.data);
					return;
				}
				const {
					label
				} = this.options;

				let data = this.data.filter((item) => item[label].includes(value));

				this.init(data);
			},
			
			
			/**
			 *
			 */
			handleFormatData(data) {
				let len = data.length;
				const {
					children,
					value,
					label
				} = this.options;
				for (let i = 0; i < len; i++) {
					let item = data[i];
					if (item[children] && item[children].length > 0) {
						this.handleFormatData(item[children]);
						item[children].unshift({
							[value]: "",
							[label]: "",
						});
					}
				}
			},
			/**
			 * 处理默认值是数组时的情况
			 * 解决不同父级，相同子级的数据展示问题
			 * @param {Array} arr
			 */
			handleFormatDefaultOfArray(arr) {
				let len = arr.length;
				if (len < 1) {
					return;
				}
				const {
					value,
					children
				} = this.options;
				//
				let selectData = this.viewData[0];
				let selectIndexs = [];
				let selectValues = [];
				for (let i = 0; i < len; i++) {
					let info = arr[i];
					let index = selectData.findIndex((item) => item[value] == info[value]);

					if (index > -1) {
						selectIndexs.push(index);
						selectValues.push(selectData[index]);
						selectData = selectData[index][children] || [];
					}
				}
				if (selectIndexs.length < 1) {
					// 没有找到对应的数据，直接显示给定值
					this.selectValue = arr;
					return;
				}
				this.selectIndex = [...selectIndexs];
				this.selectValue = [...selectValues];
			},
			/**
			 *
			 * @param {Object} info
			 */
			handleFormatDefault(info) {
				this.selectValue = [];
				this.selectIndex = [];
				let $this = this;

				// 接受默认值参数为数组，填充默认值
				if (Array.isArray(info)) {
					this.handleFormatDefaultOfArray(info);
					return;
				}
				const {
					value,
					children
				} = this.options;

				let selectedValue = info[value];
				if (selectedValue === undefined) {
					return;
				}
				/**
				 * 递归查找选中的数据
				 * @param {Object} p
				 * @param {Object} index
				 */
				function deepFind(p, index) {
					if (p[value] == selectedValue) {
						return [
							[p],
							[index]
						];
					}
					if (!p[children] || p[children].length < 1) {
						return [];
					}
					let len = p[children].length;
					let res = [];

					for (let i = 0; i < len; i++) {
						const [values, indexs] = deepFind(p[children][i], i);
						if (values && values.length > 0) {
							res = [
								[p],
								[index]
							];
							res[0].push(...values);
							res[1].push(...indexs);
							break;
						}
					}

					return res;
				}
				let data = this.viewData[0];
				for (let i = 0, len = data.length; i < len; i++) {
					let item = data[i];

					let [values, indexs] = deepFind(item, i);
					if (values && values.length > 0) {
						// arr.push(info);
						this.selectValue = values;
						this.selectIndex = indexs;
						return;
					}
				}
				// 没有找到对应的数据，直接显示给定值
				this.selectValue = [info];
			},
			initViewData() {
				const {
					children
				} = this.options;

				if (this.selectIndex.length < 1) {
					this.selectIndex.push(0);
				}
				if (this.clearable && this.selectIndex[0] == 0) {
					// 可清除，默认选择的第一个
					return;
				}
				let data = this.viewData[0];
				let index = 0;
				let info = data[this.selectIndex[index]];
				// 默认值选中
				while (info && info[children] && info[children].length > 0) {
					let nextData = info[children];
					// 默认第一条数据
					this.viewData.push(nextData);
					// 处理默认值
					index++;
					if (this.selectIndex[index] !== undefined) {
						// 继续处理下一层级的选择数据
						info = nextData[this.selectIndex[index]];
					} else {
						info = nextData[0];
						this.selectIndex.push(0);
					}
				}

				// 数据初始化后，调用一次懒加载

				if (this.lazy) {
					let columnIndex = 0;
					if (this.selectIndex.length > 0) {
						columnIndex = this.selectIndex.length - 1;
					}
					this.handleLazyLoad({
						column: columnIndex,
						value: 0,
					});
				}
			},
			/**
			 * 异步加载时，逻辑处理，数据由内部直接处理
			 *
			 */
			handleLazyLoad({
				column
			}) {
				let $this = this;
				const {
					value,
					label
				} = this.options;

				// 解决 不同父级、同一子级的问题，懒加载后默认选中该子级
				// this.selectIndex.length = column + 1;
				this.viewData.length = column + 1;

				// let selectValues = this.selectIndex.map((val, index) => this.viewData[index][val]);
				let selectValues = this.viewData.map(
					(items, index) => items[this.selectIndex[index]]
				);

				if (!selectValues[column]) {
					return;
				}
				this.load(selectValues[column], selectValues, (data) => {
					// 回调、处理异步加载数据
					if (Array.isArray(data) && data.length > 0) {
						// 是否严格遵循父子节点不关联
						if ($this.checkStrictly) {
							data.unshift({
								[value]: "",
								[label]: "",
							});
						}

						$this.viewData.push(data);

						// 处理默认值
						// 优先使用 this.selectIndex ；没有选中值，再用默认值value
						/**
						 * 2024-03-04
						 * 修复：查找懒加载数据中是否存在之前选中的值，没有则默认选中 第一条数据 0 ；
						 *
						 */

						let selectIndex = -1;
						let isInitSelect = false;
						if ($this.selectIndex[column + 1] !== undefined) {
							// 数据中是否存在之前选中数据
							selectIndex = data.findIndex(
								(item) => item[value] == $this.selectValue[column + 1][value]
							);
							// selectIndex = $this.selectIndex[column+1];
						} else if ($this.value[column + 1] !== undefined) {
							// 处理默认选中
							selectIndex = data.findIndex(
								(item) => item[value] == $this.value[column + 1][value]
							);
							isInitSelect = true;
						}
						if (selectIndex < 0) {
							selectIndex = 0;
						}

						// 等待列数据渲染完毕
						$this.$nextTick(() => {
							$this.handleChange({
								detail: {
									column: column + 1,
									value: selectIndex,
								},
							});
							if (isInitSelect) {
								// 有默认值，懒加载，处理选中的数据
								$this.selectValue.push(data[selectIndex]);
							}
						});
					} else {
						// 下级无数据
						this.selectIndex.length = column + 1;
					}
				});
			},
			handleChange({
				detail
			}) {
				let {
					column,
					value
				} = detail;
				const {
					children
				} = this.options;

				let info = this.viewData[column][value];
				// 修复nvue问题
				// this.selectIndex[column] = value;
				this.selectIndex.splice(column, 1, value);

				// 懒加载，外部加载更新下一层级数据
				if (
					this.lazy &&
					(!info || !info[children] || info[children].length < 1)
				) {
					this.handleLazyLoad(detail);
					return;
				}

				// 下一层级
				let nextColumn = column + 1;
				if (!info || !info[children] || info[children].length < 1) {
					// 没有下一层级，则移除viewData 已有的数据；
					this.viewData.length = nextColumn;
					this.selectIndex.length = nextColumn;
					return;
				}

				while (info[children] && info[children].length > 0) {
					let prevColumnData = this.viewData[nextColumn] || [];
					// 默认第一条数据
					if (this.viewData[nextColumn]) {
						// 修复nvue问题
						// this.viewData[nextColumn] = info[children]
						this.viewData.splice(nextColumn, 1, info[children]);
					} else {
						this.viewData.push(info[children]);
					}
					// 重置其他column选择值位0
					// 不重置，相同子级同样选中
					let isSame = this.comparePrevColumnData(
						prevColumnData,
						this.viewData[nextColumn],
						nextColumn
					);
					if (!isSame) {
						this.selectIndex.splice(nextColumn, 1, 0);
					}
					nextColumn += 1;
					info = info[children][0];
				}

				this.viewData.length = nextColumn;
				this.selectIndex.length = nextColumn;

				// 调用一次默认选中，触发懒加载判断
				this.handleChange({
					detail: {
						column: nextColumn - 1,
						value: this.selectIndex[nextColumn - 1],
					},
				});
			},
			handleConfirm() {
				this.selectValue = this.selectIndex.map(
					(val, index) => this.viewData[index][val]
				);

				// 选中值
				// 最后一个选中对象
				let suffix = this.selectValue[this.selectValue.length - 1];
				if (this.checkStrictly && suffix.value === "") {
					this.selectValue.pop();
				}

				this.$emit(
					"ok",
					this.selectValue[this.selectValue.length - 1],
					this.selectValue
				);
				
			},
			handleClose() {
				this.$emit("close");
			},
			comparePrevColumnData(pre, cur, index) {
				const {
					value
				} = this.options;

				if (!pre[index] || !cur[index]) {
					return false;
				}
				return pre[index][value] == cur[index][value];
			},
		},
	};
</script>

<style lang="less" scoped>
	.ifun-tree-picker {
		width: 100%;
		height: 100%;
		position: relative;
		z-index: 9999;
		.picker-label-placeholder {
			opacity: 0.4;
		}
	}
</style>